/**
 * HTTP请求工具
 * @description 基于axios封装的HTTP请求工具，包含请求拦截、响应拦截、错误处理等
 * @author CRM开发团队
 * @version 1.0.0
 */

import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios'
import { ElMessage, ElMessageBox } from 'element-plus'
import { useUserStore } from '@/stores/user'

// 响应数据接口
export interface ApiResponse<T = any> {
  code: number
  message: string
  data: T
  timestamp: string
  traceId?: string
}

// 请求配置接口
export interface RequestConfig extends AxiosRequestConfig {
  skipErrorHandler?: boolean  // 跳过全局错误处理
  showLoading?: boolean      // 显示加载状态
  showErrorMessage?: boolean // 显示错误消息
}

// 错误码映射
const ERROR_CODE_MAP: Record<number, string> = {
  400: '请求参数错误',
  401: '未授权，请重新登录',
  403: '权限不足，拒绝访问',
  404: '请求的资源不存在',
  405: '请求方法不允许',
  408: '请求超时',
  409: '请求冲突',
  422: '数据验证失败',
  429: '请求过于频繁，请稍后再试',
  500: '服务器内部错误',
  502: '网关错误',
  503: '服务不可用',
  504: '网关超时'
}

// 业务错误码映射
const BUSINESS_ERROR_MAP: Record<number, string> = {
  10001: '客户不存在',
  10002: '身份证号已存在',
  10003: '手机号已存在',
  10004: '客户状态不允许此操作',
  10005: '敏感信息访问权限不足',
  10006: '客户数据完整性验证失败',
  10007: '客户标签数量超限',
  10008: '操作记录查询权限不足'
}

class RequestService {
  private instance: AxiosInstance
  private pendingRequests: Map<string, AbortController> = new Map()

  constructor() {
    this.instance = axios.create({
      baseURL: import.meta.env.VITE_API_BASE_URL || '/api',
      timeout: 30000,
      headers: {
        'Content-Type': 'application/json'
      }
    })

    this.setupInterceptors()
  }

  /**
   * 设置请求拦截器和响应拦截器
   */
  private setupInterceptors(): void {
    // 请求拦截器
    this.instance.interceptors.request.use(
      (config) => {
        // 添加认证token
        const userStore = useUserStore()
        const token = userStore.token
        if (token) {
          config.headers.Authorization = `Bearer ${token}`
        }

        // 添加请求追踪ID
        config.headers['X-Request-ID'] = this.generateRequestId()

        // 暂时禁用重复请求取消机制
        // const requestKey = this.getRequestKey(config)
        // this.cancelPendingRequest(requestKey)
        // 
        // const controller = new AbortController()
        // config.signal = controller.signal
        // this.pendingRequests.set(requestKey, controller)

        // 添加时间戳防止缓存
        if (config.method === 'get') {
          config.params = {
            ...config.params,
            _t: Date.now()
          }
        }

        return config
      },
      (error) => {
        return Promise.reject(error)
      }
    )

    // 响应拦截器
    this.instance.interceptors.response.use(
      (response: AxiosResponse<ApiResponse>) => {
        // 清除已完成的请求
        const requestKey = this.getRequestKey(response.config)
        this.pendingRequests.delete(requestKey)

        const { data } = response
        
        // 检查业务状态码
        if (data.code !== 200) {
          return this.handleBusinessError(data, response.config as RequestConfig)
        }

        return response
      },
      (error: AxiosError) => {
        // 清除已完成的请求
        if (error.config) {
          const requestKey = this.getRequestKey(error.config)
          this.pendingRequests.delete(requestKey)
        }

        return this.handleError(error)
      }
    )
  }

  /**
   * 处理业务错误
   */
  private handleBusinessError(data: ApiResponse, config: RequestConfig): Promise<never> {
    const errorMessage = BUSINESS_ERROR_MAP[data.code] || data.message || '业务处理失败'
    
    if (config.showErrorMessage !== false) {
      ElMessage.error(errorMessage)
    }

    const error = new Error(errorMessage)
    ;(error as any).code = data.code
    ;(error as any).data = data
    
    return Promise.reject(error)
  }

  /**
   * 处理HTTP错误
   */
  private handleError(error: AxiosError): Promise<never> {
    let errorMessage = '网络请求失败'

    if (error.code === 'ECONNABORTED') {
      errorMessage = '请求超时，请稍后再试'
    } else if (error.response) {
      const { status } = error.response
      errorMessage = ERROR_CODE_MAP[status] || `请求失败 (${status})`
      
      // 处理401未授权
      if (status === 401) {
        this.handleUnauthorized()
      }
    } else if (error.request) {
      errorMessage = '网络连接失败，请检查网络'
    }

    // 显示错误消息
    if (!(error.config as RequestConfig)?.showErrorMessage === false) {
      ElMessage.error(errorMessage)
    }

    return Promise.reject(error)
  }

  /**
   * 处理未授权情况
   */
  private handleUnauthorized(): void {
    const userStore = useUserStore()
    
    ElMessageBox.confirm(
      '登录状态已过期，请重新登录',
      '系统提示',
      {
        confirmButtonText: '重新登录',
        cancelButtonText: '取消',
        type: 'warning'
      }
    ).then(() => {
      userStore.logout()
      window.location.reload()
    }).catch(() => {
      // 用户取消
    })
  }

  /**
   * 生成请求唯一标识
   */
  private getRequestKey(config: AxiosRequestConfig): string {
    const { method, url, params, data } = config
    return `${method}:${url}:${JSON.stringify(params)}:${JSON.stringify(data)}`
  }

  /**
   * 取消待处理的请求
   */
  private cancelPendingRequest(requestKey: string): void {
    const controller = this.pendingRequests.get(requestKey)
    if (controller) {
      controller.abort()
      this.pendingRequests.delete(requestKey)
    }
  }

  /**
   * 生成请求ID
   */
  private generateRequestId(): string {
    return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
  }

  /**
   * 通用请求方法
   */
  async request<T = any>(config: RequestConfig): Promise<ApiResponse<T>> {
    try {
      const response = await this.instance.request<ApiResponse<T>>(config)
      return response.data
    } catch (error) {
      throw error
    }
  }

  /**
   * GET请求
   */
  async get<T = any>(url: string, params?: any, config?: RequestConfig): Promise<ApiResponse<T>> {
    return this.request<T>({
      method: 'GET',
      url,
      params,
      ...config
    })
  }

  /**
   * POST请求
   */
  async post<T = any>(url: string, data?: any, config?: RequestConfig): Promise<ApiResponse<T>> {
    return this.request<T>({
      method: 'POST',
      url,
      data,
      ...config
    })
  }

  /**
   * PUT请求
   */
  async put<T = any>(url: string, data?: any, config?: RequestConfig): Promise<ApiResponse<T>> {
    return this.request<T>({
      method: 'PUT',
      url,
      data,
      ...config
    })
  }

  /**
   * DELETE请求
   */
  async delete<T = any>(url: string, data?: any, config?: RequestConfig): Promise<ApiResponse<T>> {
    return this.request<T>({
      method: 'DELETE',
      url,
      data,
      ...config
    })
  }

  /**
   * PATCH请求
   */
  async patch<T = any>(url: string, data?: any, config?: RequestConfig): Promise<ApiResponse<T>> {
    return this.request<T>({
      method: 'PATCH',
      url,
      data,
      ...config
    })
  }

  /**
   * 上传文件
   */
  async upload<T = any>(url: string, file: File, config?: RequestConfig): Promise<ApiResponse<T>> {
    const formData = new FormData()
    formData.append('file', file)

    return this.request<T>({
      method: 'POST',
      url,
      data: formData,
      headers: {
        'Content-Type': 'multipart/form-data'
      },
      ...config
    })
  }

  /**
   * 下载文件
   */
  async download(url: string, params?: any, filename?: string): Promise<void> {
    try {
      const response = await this.instance.request({
        method: 'GET',
        url,
        params,
        responseType: 'blob'
      })

      const blob = new Blob([response.data])
      const downloadUrl = window.URL.createObjectURL(blob)
      const link = document.createElement('a')
      link.href = downloadUrl
      link.download = filename || `download_${Date.now()}`
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
      window.URL.revokeObjectURL(downloadUrl)
    } catch (error) {
      ElMessage.error('文件下载失败')
      throw error
    }
  }

  /**
   * 取消所有待处理的请求
   */
  cancelAllRequests(): void {
    this.pendingRequests.forEach((controller) => {
      controller.abort()
    })
    this.pendingRequests.clear()
  }

  /**
   * 设置通用请求头
   */
  setCommonHeaders(headers: Record<string, string>): void {
    Object.assign(this.instance.defaults.headers.common, headers)
  }

  /**
   * 移除通用请求头
   */
  removeCommonHeader(key: string): void {
    delete this.instance.defaults.headers.common[key]
  }

  /**
   * 设置基础URL
   */
  setBaseURL(baseURL: string): void {
    this.instance.defaults.baseURL = baseURL
  }

  /**
   * 设置超时时间
   */
  setTimeout(timeout: number): void {
    this.instance.defaults.timeout = timeout
  }
}

// 创建请求实例
export const requestService = new RequestService()

// 导出便捷方法
export const request = requestService.request.bind(requestService)
export const get = requestService.get.bind(requestService)
export const post = requestService.post.bind(requestService)
export const put = requestService.put.bind(requestService)
export const del = requestService.delete.bind(requestService)
export const patch = requestService.patch.bind(requestService)
export const upload = requestService.upload.bind(requestService)
export const download = requestService.download.bind(requestService)

export default requestService